home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Power 1997 December
/
MACPOWER-1997-12.ISO.7z
/
MACPOWER-1997-12.ISO
/
AMUG
/
PROGRAMMING
/
Raven 1.2 Examples.sit
/
Raven 1.2 Examples
/
Quill
/
Source
/
ResourceMap.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-03
|
12KB
|
500 lines
/*
* File: ResourceMap.cpp
* Summary: A class that knows how to manage resources of a specified type. The
* resource data is kept in memory so this class is unsuitable for large
* resources.
* Written by: Jesse Jones
*
* Copyright ゥ 1996 Jesse Jones. Permission to use, copy, modify, and distribute this
* file as source or object code is hereby granted without fee. Permission to sell the
* source code is granted only to non-profit institutions. This file is provided "as is"
* without express or implied warranty.
*
* Change History (most recent first):
*
* <-> 8/15/96 JDJ Created
*/
#include "ResourceMap.h"
#include <Map.h>
#include <Resources.h>
#include <ZCommand.h>
#include <ZDragSession.h>
#include <ZExceptions.h>
#include <ZHandleStream.h>
#include <ZLocker.h>
#include <ZResUtils.h>
#include <ZStream.h>
#include <ZStringUtils.h>
// ===================================================================================
// struct SResourceMapMessage
// ===================================================================================
//---------------------------------------------------------------
//
// SResourceMapMessage::SResourceMapMessage
//
//---------------------------------------------------------------
SResourceMapMessage::SResourceMapMessage(CResourceMap* rMap, ResID id, long mesg)
{
ASSERT(rMap != nil);
rsrcMap = rMap;
if (mesg != kDeletingResources)
oldRsrc = newRsrc = rsrcMap->GetResource(id);
message = mesg;
}
#pragma mark -
//---------------------------------------------------------------
//
// SResource::SResource
//
//---------------------------------------------------------------
SResource::SResource(const TDragSession& session, ItemReference item, FlavorType flavor)
{
THandle data = session.GetData(item, flavor);
TInHandleStream stream(data);
stream >> *this;
}
//---------------------------------------------------------------
//
// operator>> (SResource)
//
//---------------------------------------------------------------
TInStream& operator>>(TInStream& stream, SResource& value)
{
Handle hand = value.data;
stream >> value.id >> value.name >> hand;
return stream;
}
//---------------------------------------------------------------
//
// operator<< (SResource)
//
//---------------------------------------------------------------
TOutStream& operator<<(TOutStream& stream, const SResource& value)
{
stream << value.id << value.name << value.data;
return stream;
}
//---------------------------------------------------------------
//
// SResource::AddData
//
//---------------------------------------------------------------
void SResource::AddData(TDragSession& session, ItemReference item, FlavorType flavor, FlavorFlags flags) const
{
THandle bits;
{
TOutHandleStream stream(bits);
stream << *this;
}
{
TLocker lock(bits);
session.AddData(item, flavor, bits.GetPtr(), bits.GetSize(), flags);
}
}
#pragma mark -
// ===================================================================================
// class CResourceMap
// ===================================================================================
//---------------------------------------------------------------
//
// CResourceMap::~CResourceMap
//
//---------------------------------------------------------------
CResourceMap::~CResourceMap()
{
delete mResources;
}
//---------------------------------------------------------------
//
// CResourceMap::CResourceMap
//
//---------------------------------------------------------------
CResourceMap::CResourceMap(ResType type)
{
ASSERT(type != '????');
mType = type;
mResources = new ResourceMap;
}
//---------------------------------------------------------------
//
// CResourceMap::ReadResources
//
//---------------------------------------------------------------
void CResourceMap::ReadResources()
{
// Zap any old resources that may be hanging around
if (mResources->size() > 0)
this->Broadcast(SResourceMapMessage(this, 0, kDeletingResources));
mResources->erase(mResources->begin(), mResources->end());
// Resource zapping may cause resource windows to be closed.
// To ensure that this doesn't overwrite the data we're about
// to read we'll execute pending deferred deletes here.
TCommand::ExecuteCommands(false);
// and read in the new resources.
short numViews = ::Count1Resources(mType);
for (short index = 1; index <= numViews; index++) {
Handle hand = ::Get1IndResource(mType, index);
ThrowIfResFail(hand);
ResID id;
ResType type;
Str255 name;
::GetResInfo(hand, &id, &type, name);
ThrowIfResError();
this->AddResource(SResource(id, PStrToStr(name), hand));
}
}
//---------------------------------------------------------------
//
// CResourceMap::WriteResources
//
// ・・・ハrewrite this so that an error while writing the new data
// ・・・ハout doesn't trash all of the old data
//
//---------------------------------------------------------------
void CResourceMap::WriteResources()
{
// Out with the old...
Delete1Resource(mType);
// and in with the new.
ResourceMap::iterator iter = mResources->begin();
while (iter != mResources->end()) {
ResourceEntry& entry = *iter++;
ResID id = entry.first;
SResourceData& data = entry.second;
long size = data.hand.GetSize();
Handle rsrc = ::NewHandle(size);
ThrowIfMemFail(rsrc);
::BlockMoveData(data.hand.GetUnsafePtr(), *rsrc, size);
::AddResource(rsrc, mType, id, StrToPStr(data.name));
ThrowIfResError();
::ReleaseResource(rsrc);
data.dirty = false;
this->Broadcast(SResourceMapMessage(this, id, kSavedResource));
}
}
//---------------------------------------------------------------
//
// CResourceMap::GetNumResources
//
//---------------------------------------------------------------
long CResourceMap::GetNumResources() const
{
return mResources->size();
}
//---------------------------------------------------------------
//
// CResourceMap::GetLastResourceID
//
//---------------------------------------------------------------
ResID CResourceMap::GetLastResourceID() const
{
ResID lastID = 255;
if (mResources->size() > 0) {
ResourceMap::reverse_iterator iter = mResources->rbegin();
const ResourceEntry& entry = *iter++;
lastID = entry.first;
}
return lastID;
}
//---------------------------------------------------------------
//
// CResourceMap::GetResourceName
//
//---------------------------------------------------------------
string CResourceMap::GetResourceName(ResID id) const
{
ASSERT(mResources->count(id) == 1);
const SResourceData& data = mResources->operator[](id);
return data.name;
}
//---------------------------------------------------------------
//
// CResourceMap::GetResourceData
//
//---------------------------------------------------------------
THandle CResourceMap::GetResourceData(ResID id) const
{
ASSERT(mResources->count(id) == 1);
const SResourceData& data = mResources->operator[](id);
return data.hand;
}
//---------------------------------------------------------------
//
// CResourceMap::GetResource
//
//---------------------------------------------------------------
SResource CResourceMap::GetResource(ResID id) const
{
ASSERT(mResources->count(id) == 1);
const SResourceData& data = mResources->operator[](id);
return SResource(id, data.name, data.hand);
}
//---------------------------------------------------------------
//
// CResourceMap::IsDirty ()
//
//---------------------------------------------------------------
bool CResourceMap::IsDirty() const
{
bool dirty = false;
ResourceMap::const_iterator iter = mResources->begin();
while (!(iter == mResources->end()) && !dirty) { // CW Pro 1 has problems finding operator!= when precompiling SGI STL
const ResourceEntry& entry = *iter++;
const SResourceData& data = entry.second;
dirty = data.dirty;
}
return dirty;
}
//---------------------------------------------------------------
//
// CResourceMap::IsDirty (ResID)
//
//---------------------------------------------------------------
bool CResourceMap::IsDirty(ResID id) const
{
ASSERT(mResources->count(id) == 1);
const SResourceData& data = mResources->operator[](id);
return data.dirty;
}
//---------------------------------------------------------------
//
// CResourceMap::ClearDirty ()
//
//---------------------------------------------------------------
void CResourceMap::ClearDirty()
{
ResourceMap::iterator iter = mResources->begin();
while (iter != mResources->end()) {
ResourceEntry& entry = *iter++;
SResourceData& data = entry.second;
data.dirty = false;
}
}
//---------------------------------------------------------------
//
// CResourceMap::ClearDirty (ResID)
//
//---------------------------------------------------------------
void CResourceMap::ClearDirty(ResID id)
{
ASSERT(mResources->count(id) == 1);
SResourceData& data = mResources->operator[](id);
data.dirty = false;
}
//---------------------------------------------------------------
//
// CResourceMap::SetResourceName
//
//---------------------------------------------------------------
void CResourceMap::SetResourceName(ResID id, const string& newName)
{
ASSERT(mResources->count(id) == 1);
SResourceData& data = mResources->operator[](id);
if (data.name != newName) {
SResourceMapMessage mesg(this, id, kSetResourceName);
data.name = newName;
data.dirty = true;
mesg.newRsrc.name = newName;
this->Broadcast(mesg);
}
}
//---------------------------------------------------------------
//
// CResourceMap::SetResourceData
//
//---------------------------------------------------------------
void CResourceMap::SetResourceData(ResID id, const THandle& newHand)
{
ASSERT(mResources->count(id) == 1);
SResourceData& data = mResources->operator[](id);
if (newHand != data.hand) {
// Do this the hard way to avoid invalidating objects that have
// a copy of data.hand
long bytes = newHand.GetSize();
data.hand.SetSize(bytes);
BlockMoveData(newHand.GetUnsafePtr(), data.hand.GetUnsafePtr(), bytes);
data.dirty = true;
this->Broadcast(SResourceMapMessage(this, id, kSetResourceData));
}
}
//---------------------------------------------------------------
//
// CResourceMap::SetResourceID
//
//---------------------------------------------------------------
void CResourceMap::SetResourceID(ResID oldID, ResID newID)
{
ASSERT(mResources->count(oldID) == 1);
if (oldID != newID) {
ASSERT(mResources->count(newID) == 0);
SResourceMapMessage mesg(this, oldID, kSetResourceID);
string name = this->GetResourceName(oldID);
THandle data = this->GetResourceData(oldID);
mResources->erase(oldID);
mResources->insert(ResourceEntry(newID, SResourceData(data, name, true)));
mesg.newRsrc.id = newID;
this->Broadcast(mesg);
}
ASSERT(mResources->count(newID) == 1);
}
//---------------------------------------------------------------
//
// CResourceMap::AddResource ()
//
//---------------------------------------------------------------
ResID CResourceMap::AddResource()
{
ResID id = this->GetLastResourceID() + 1;
ASSERT(mResources->count(id) == 0);
mResources->insert(ResourceEntry(id, SResourceData(THandle(), "", true)));
this->Broadcast(SResourceMapMessage(this, id, kAddedResource));
return id;
}
//---------------------------------------------------------------
//
// CResourceMap::AddResource (SResource)
//
//---------------------------------------------------------------
void CResourceMap::AddResource(const SResource& rsrc)
{
ASSERT(mResources->count(rsrc.id) == 0);
mResources->insert(ResourceEntry(rsrc.id, SResourceData(rsrc.data, rsrc.name, true)));
this->Broadcast(SResourceMapMessage(this, rsrc.id, kAddedResource));
}
//---------------------------------------------------------------
//
// CResourceMap::DeleteResource
//
//---------------------------------------------------------------
void CResourceMap::DeleteResource(ResID id)
{
ASSERT(mResources->count(id) == 1);
SResourceMapMessage mesg(this, id, kDeletedResource);
mResources->erase(id);
this->Broadcast(mesg);
}
//---------------------------------------------------------------
//
// CResourceMap::HasResource
//
//---------------------------------------------------------------
bool CResourceMap::HasResource(ResID id) const
{
return mResources->count(id) == 1;
}